import {
	ExpCtrlActionType,
	IExpCtrlAbility,
	IExpCtrlController,
	IExpCtrlModel,
	IExpCtrlStore,
	IMDCtrlAbility,
	IParam,
	MDCtrlActionType,
} from '@/core/interface';
import { computedNavData, deepCopy } from '@/core/utils';
import { DECtrlController } from './de-ctrl-controller';

/**
 * 导航部件控制器
 *
 * @export
 * @class ExpCtrlController
 * @extends {(DECtrlController<T | ExpCtrlActionType, S, A>)}
 * @implements {IExpCtrlController<S, A>}
 * @template T
 * @template S
 * @template A
 */
export class ExpCtrlController<
		T,
		S extends IExpCtrlStore,
		A extends IExpCtrlAbility
	>
	extends DECtrlController<T | ExpCtrlActionType, S, A>
	implements IExpCtrlController<S, A>
{
	/**
	 * 部件模型
	 *
	 * @type {IExpCtrlModel}
	 * @memberof ExpCtrlController
	 */
	protected declare readonly model: IExpCtrlModel;

	/**
	 * 快速搜索值
	 *
	 * @param {string}
	 * @memberof ExpCtrlController
	 */
	public searchValue = '';

	/**
	 * 获取多数据部件能力
	 *
	 * @protected
	 * @return {*}  {(IMDCtrlAbility | undefined)}
	 * @memberof ExpCtrlController
	 */
	protected getMDCtrlAbility(): IMDCtrlAbility | undefined {
		return this.getSubAbility<IMDCtrlAbility>(this.model.xDataCtrlName);
	}

	/**
	 * 搜索
	 *
	 * @param {string} searchValue
	 * @memberof ExpCtrlController
	 */
	public search(searchValue: string) {
		this.searchValue = searchValue;
		const mdCtrl = this.getMDCtrlAbility();
		if (mdCtrl) {
			mdCtrl.load({ query: searchValue });
		}
	}

	/**
	 * 导航部件加载数据
	 *
	 * @param {IParam} [opts={}]
	 * @memberof ExpCtrlController
	 */
	public load(opts: IParam = {}): void {
		const mdCtrl = this.getMDCtrlAbility();
		if (mdCtrl) {
			const tempViewParams = deepCopy(this.store.viewParams);
			mdCtrl.load(Object.assign(tempViewParams, opts));
			return;
		}
	}

	/**
	 * 计算导航工具栏权限
	 *
	 * @protected
	 * @param {boolean} state
	 * @param {IParam} [data]
	 * @memberof ExpCtrlController
	 */
	protected calcNavigateToolbarState(state: boolean, data?: IParam) {
		//  TODO 计算工具栏权限
	}

	/**
	 * 处理选中数据改变
	 *
	 * @param {IParam[]} selection
	 * @memberof ExpCtrlController
	 */
	handleSelectionChange(selections: IParam[]): void {
		if (!selections || selections.length === 0) {
			this.calcNavigateToolbarState(true);
			return;
		}
		const select = selections[0];
		const { context, viewParams } = this.store;
		const {
			xDataCtrlName,
			xDataDeCodeName,
			navFilter,
			navPSDer,
			navigateContext,
			navigateParams,
			navViewName,
		} = this.model;
		const tempContext = deepCopy(context);
		const tempViewParams = deepCopy(viewParams);
		if (xDataCtrlName) {
			if (xDataDeCodeName) {
				Object.assign(tempContext, {
					[xDataDeCodeName]: select[xDataDeCodeName],
					srfparentkey: select[xDataDeCodeName],
					srfparentdename: xDataDeCodeName,
					srfparentdemapname: '',
				});
				//  导航过滤参数
				if (navFilter) {
					Object.assign(tempViewParams, {
						[navFilter]: select[xDataDeCodeName],
					});
				}
				//  导航关系
				if (navPSDer) {
					Object.assign(tempViewParams, {
						[navPSDer]: select[xDataDeCodeName],
					});
				}
			}
			if (navigateContext) {
				const _context = computedNavData(
					select,
					tempContext,
					tempViewParams,
					navigateContext
				);
				Object.assign(tempContext, _context);
			}
			if (navigateParams) {
				const _viewParams = computedNavData(
					select,
					tempContext,
					tempViewParams,
					navigateParams
				);
				Object.assign(tempViewParams, _viewParams);
			}
			const param = [
				{
					data: select,
					navViewName,
					srfnavdata: {
						context: tempContext,
						viewParams: tempViewParams,
					},
				},
			];
			this.calcNavigateToolbarState(
				xDataDeCodeName && select[xDataDeCodeName] ? false : true,
				select
			);
			this.emit('selectionChange', param);
		} else {
			this.calcNavigateToolbarState(true);
			console.warn('未配置多数据部件');
		}
	}

	/**
	 * 处理多数据部件加载之前
	 *
	 * @protected
	 * @param {IParam[]} data
	 * @memberof ExpCtrlController
	 */
	protected handleMDCtrlBeforeLoad(data: IParam[]) {
		const param = data && data.length > 0 ? data[0] : {};
		Object.assign(param, { query: this.searchValue });
		this.emit('beforeLoad', data);
	}

	/**
	 * 处理多数据部件行为
	 *
	 * @template T
	 * @param {(T | MDCtrlEventActionType)} action
	 * @param {IParam[]} data
	 * @memberof ExpCtrlController
	 */
	protected handleMDCtrlAction<T>(
		action: T | MDCtrlActionType,
		data: IParam[]
	) {
		if (action === 'beforeLoad') {
			this.handleMDCtrlBeforeLoad(data);
		}
		if (action === 'selectionChange') {
			this.handleSelectionChange(data);
		}
	}

	/**
	 * 处理子部件行为
	 *
	 * @param {string} name
	 * @param {ExpCtrlActionType} action
	 * @param {IParam[]} data
	 * @memberof ExpCtrlController
	 */
	handleCtrlAction(name: string, action: MDCtrlActionType, data: IParam[]) {
		super.handleCtrlAction(name, action, data);
		const mdCtrl = this.getMDCtrlAbility();
		if (mdCtrl && name === mdCtrl.name) {
			this.handleMDCtrlAction(action as MDCtrlActionType, data);
			return;
		}
	}

	/**
	 * 获取部件能力
	 *
	 * @return {*}  {A}
	 * @memberof ExpCtrlController
	 */
	public getAbility(): A {
		return {
			...super.getAbility(),
			load: this.load.bind(this),
		};
	}
}
